package com.ndood.reconciliation.app.async;

import java.util.Optional;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import com.ndood.reconciliation.app.redis.RedisReconKeyHelper;
import com.ndood.reconciliation.app.redis.RedisTool;
import com.ndood.reconciliation.base.enums.EnumPayway;
import com.ndood.reconciliation.base.pojo.ReconInfo;
import com.ndood.reconciliation.domain.service.AlipayReconService;

import lombok.extern.slf4j.Slf4j;

@Service
@Slf4j
public class ThreadReconExecuter {

	private boolean flag = true;

	@Autowired
	RedisTool redisTool;
	
	@Autowired
	private AlipayReconService alipayReconService;

	public void startReconciliation() {
		for (int i = 0; i < Metrics.CONCURRENCY; i++) {
			final int finalI = i;
			
			Metrics.m(() -> {
				log.info("Reconciliation service start, thread: " + finalI);
				
				while (flag) {
					try {
						
						// Setp1: 从队列获取reconKey，如果key不存在则将缓存队列转换成实时队列
						Optional<String> optReconKey = redisTool.spopReconKeyFromSnapchat();
						if (!optReconKey.isPresent()) {
							redisTool.createSnapchat();
							try {
								Thread.sleep(500);
							} catch (InterruptedException ignored) {
							}
							continue;
						}
						String reconKey = optReconKey.get();
						
						// Step2: 获取分布式锁，如果没获取到，说明该批次对账任务正在执行，则把任务重新加到缓存队列
						boolean lock = redisTool.getLock(reconKey);
						if (!lock) {
							redisTool.saddReconKey(reconKey);
							continue;
						}
						
						// Step3: 如果获取到，则处理对账任务。处理完成后释放锁
						try {
							ReconInfo reconInfo = RedisReconKeyHelper.getReconInfo(reconKey);
							if (reconInfo.getPayway().equals(EnumPayway.ALIPAY)) {
								// 进行支付宝对账
								alipayReconService.doWithReconciliation(reconInfo);
							}
							if (reconInfo.getPayway().equals(EnumPayway.WECHAT)) {
								// TODO 进行微信对账
							}
							if (reconInfo.getPayway().equals(EnumPayway.UNION)) {
								// TODO 进行银联对账
							}
						} finally {
							redisTool.delLock(reconKey);
						}
						
					} catch (Exception e) {
						Throwable throwable = e.getCause();
						while (throwable != null) {
							log.error(throwable.getMessage(), throwable);
							throwable = throwable.getCause();
						}
					}
					
				}
				log.info("ServiceHandler unicast end, thread: " + finalI);
			});
		}
	}

}